#!/bin/sh

# Copyright (c) 2020 IBM Corp.

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

set -eu

: ${OTPTOOL:=$(which otptool)}
: ${SOCSEC:=$(which socsec)}
: ${BL1_IMAGE:=tests/data/bl1.bin}
: ${RUN:=$(which coverage) run -p}

make_slug() {
	local soc=$1
	local rev=$2
	local rot_mode=$3

	shift 3

	if [ "$rot_mode" = "modegcm" ] || [ "$rot_mode" = "modeecdsa" ] || [ "$rot_mode" = "modeecdsaaes1" ]
	then
		echo -n ${soc}-${rev}_${rot_mode}

		if [ $# -ge 3 ]
		then
			if [ $1 = "cot" ]
			then
				local cot_rsa=$2
				local cot_sha=$3

				shift 3

				echo -n _cot-rsa${cot_rsa}-sha${cot_sha}
			fi
		fi
	elif [ "$rot_mode" = "modeecdsaaes2" ]
	then
		if [ $# -eq 1  ]
		then
			local rot_rsa=$1
			shift 1
			echo -n ${soc}-${rev}_${rot_mode}-rsa${rot_rsa}
		fi
	else
		local rot_rsa=$1
		local rot_sha=$2

		shift 2

		if [ $# -eq 1  ]
		then
			if [ $1 = "big" -o $1 = "little" ]
			then
				local order=$1

				shift 1

				echo -n ${soc}-${rev}_${rot_mode}-rsa${rot_rsa}-sha${rot_sha}-${order}
			else
				echo -n ${soc}-${rev}_${rot_mode}-rsa${rot_rsa}-sha${rot_sha}
			fi
		else
			echo -n ${soc}-${rev}_${rot_mode}-rsa${rot_rsa}-sha${rot_sha}
		fi

		if [ $# -ge 3 ]
		then
			if [ $1 = "cot" ]
			then
				local cot_rsa=$2
				local cot_sha=$3

				shift 3

				echo -n _cot-rsa${cot_rsa}-sha${cot_sha}
			fi
		fi
	fi

	[ $# -gt 0 ] && echo -n _$(echo $@ | tr ' ' _)

	echo
}

make_otp() {
	local soc=$1
	local rev=$2
	local rot_mode=$3

	set +u
	if [ "$rot_mode" = "modegcm" ] || [ "$rot_mode" = "modeecdsa" ] || [ "$rot_mode" = "modeecdsaaes1" ]
	then
		local otp_slug=$(make_slug $soc $rev $rot_mode)
	elif [ "$rot_mode" = "modeecdsaaes2" ]
	then
		if [ $# -eq 4 ]
		then
			local rot_rsa=$4
			local otp_slug=$(make_slug $soc $rev $rot_mode $rot_rsa)
		fi
	else
		local rot_rsa=$4
		local rot_sha=$5

		if [ $# -eq 6  ]
		then
			if [ $6 = "big" -o $6 = 'little' ]
			then
				local order=$6
				local otp_slug=$(make_slug $soc $rev $rot_mode $rot_rsa $rot_sha $order)
			else
				local otp_slug=$(make_slug $soc $rev $rot_mode $rot_rsa $rot_sha)
			fi
		else
			local otp_slug=$(make_slug $soc $rev $rot_mode $rot_rsa $rot_sha)
		fi
	fi
	set -u
	local slug=$(make_slug $@)

	$RUN $OTPTOOL \
		make_otp_image \
		--key_folder tests/keys \
		--output_folder tests/data/generated/${slug} \
		tests/otp/${otp_slug}.json
}

verify_image() {
	local soc=$1
	local rev=$2
	local slug=$(make_slug $@)

	local REV=$(echo $rev | tr '[a-z]' '[A-Z]')
	if [ $soc = "1030" ]
	then
		local soc_rev=${soc}${REV}
	else
		local soc_rev=${soc}
	fi
	echo $soc_rev
	$RUN $SOCSEC verify \
		--sec_image tests/data/generated/${slug}/bl1.signed.bin \
		--output tests/data/generated/${slug}/bl1.bin \
		--otp_image tests/data/generated/${slug}/otp-all.image
}

parse_config() {
	local args=

	if [ $# -gt 0 ]
	then
		case $1 in
		sign-stream)
			args="--signing_helper ./tests/bin/sign-stream"
			;;
		sign-file)
			args="--signing_helper_with_files ./tests/bin/sign-file"
			;;
		little)
			args="--rsa_key_order little"
			;;
		big)
			args="--rsa_key_order big"
			;;
		*)
			;;
		esac
	fi

	echo $args
}

make_mode2_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		$args

	verify_image $soc $rev mode2 $rot_rsa $rot_sha $@
}

make_mode2v2pss_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2pss $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2pss $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--deterministic \
		--rsa_padding pss \
		$args

	verify_image $soc $rev mode2v2pss $rot_rsa $rot_sha $@
}

make_mode2v2pkcs1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2pkcs1 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2pkcs1 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--rsa_key_order big \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--rsa_padding pkcs1 \
		$args

	verify_image $soc $rev mode2v2pkcs1 $rot_rsa $rot_sha $@
}

make_mode2v2aes1pss_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes1pss $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes1pss $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--key_in_otp \
		--aes_key tests/keys/aes-oem.bin \
		--deterministic \
		--rsa_padding pss \
		$args

	verify_image $soc $rev mode2v2aes1pss $rot_rsa $rot_sha $@
}

make_mode2v2aes2privpss_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes2privpss $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes2privpss $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pub.pem \
		--deterministic \
		--rsa_padding pss \
		$args

	verify_image $soc $rev mode2v2aes2privpss $rot_rsa $rot_sha $@
}

make_mode2v2aes2pubpss_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes2pubpss $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes2pubpss $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pem \
		--deterministic \
		--rsa_padding pss \
		$args

	verify_image $soc $rev mode2v2aes2pubpss $rot_rsa $rot_sha $@
}

make_mode2v2aes1pkcs1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes1pkcs1 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes1pkcs1 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--rsa_key_order big \
		--key_in_otp \
		--aes_key tests/keys/aes-oem.bin \
		--deterministic \
		--rsa_padding pkcs1 \
		$args

	verify_image $soc $rev mode2v2aes1pkcs1 $rot_rsa $rot_sha $@
}

make_mode2v2aes2privpkcs1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes2privpkcs1 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes2privpkcs1 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--rsa_key_order big \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pub.pem \
		--deterministic \
		--rsa_padding pkcs1 \
		$args

	verify_image $soc $rev mode2v2aes2privpkcs1 $rot_rsa $rot_sha $@
}

make_mode2v2aes2pubpkcs1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2v2aes2pubpkcs1 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2v2aes2pubpkcs1 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--rsa_key_order big \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pem \
		--deterministic \
		--rsa_padding pkcs1 \
		$args

	verify_image $soc $rev mode2v2aes2pubpkcs1 $rot_rsa $rot_sha $@
}

make_ecdsa_bl1_image() {
	local soc=$1
	local rev=$2
	shift 2

	local slug=$(make_slug $soc $rev modeecdsa $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev modeecdsa $@

	args=$(parse_config $@)

	echo $slug

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm ECDSA384 \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--ecdsa_sign_key tests/keys/ecdsa.pem \
		$args

	verify_image $soc $rev modeecdsa $@
}

make_ecdsaaes1_bl1_image() {
	local soc=$1
	local rev=$2
	shift 2

	local slug=$(make_slug $soc $rev modeecdsaaes1 $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev modeecdsaaes1 $@

	args=$(parse_config $@)

	echo $slug

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_ECDSA384 \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--ecdsa_sign_key tests/keys/ecdsa.pem \
		--aes_key tests/keys/aes-oem.bin \
		--key_in_otp \
		--deterministic \
		$args
	
	verify_image $soc $rev modeecdsaaes1 $@
}

make_ecdsaaes2_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	shift 3

	local slug=$(make_slug $soc $rev modeecdsaaes2 ${rot_rsa} $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev modeecdsaaes2 $rot_rsa $@

	args=$(parse_config $@)

	echo $slug

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_ECDSA384_RSA${rot_rsa} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--ecdsa_sign_key tests/keys/ecdsa.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pem \
		--deterministic \
		$args
	
	verify_image $soc $rev modeecdsaaes2 $rot_rsa $@
}


make_cot_mode2_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	local cot_rsa=$5
	local cot_sha=$6
	shift 6

	local slug=$(make_slug $soc $rev mode2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--cot_algorithm RSA${cot_rsa}_SHA${cot_sha} \
		--cot_verify_key tests/keys/rsa${cot_rsa}.pub.pem \
		$args

	verify_image $soc $rev mode2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@
}

make_mode2aes1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2aes1 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2aes1 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--key_in_otp \
		--aes_key tests/keys/aes-oem.bin \
		--deterministic \
		$args

	verify_image $soc $rev mode2aes1 $rot_rsa $rot_sha $@
}

make_cot_mode2aes1_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	local cot_rsa=$5
	local cot_sha=$6
	shift 6

	local slug=$(make_slug $soc $rev mode2aes1 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2aes1 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--key_in_otp \
		--aes_key tests/keys/aes-oem.bin \
		--cot_algorithm RSA${cot_rsa}_SHA${cot_sha} \
		--cot_verify_key tests/keys/rsa${cot_rsa}.pub.pem \
		--deterministic \
		$args

	verify_image $soc $rev mode2aes1 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@
}

make_mode2aes2_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2aes2 $rot_rsa $rot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2aes2 $rot_rsa $rot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pub.pem \
		--deterministic \
		$args

	verify_image $soc $rev mode2aes2 $rot_rsa $rot_sha $@
}

make_cot_mode2aes2_bl1_image() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	local cot_rsa=$5
	local cot_sha=$6
	shift 6

	local slug=$(make_slug $soc $rev mode2aes2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2aes2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pub.pem \
		--cot_algorithm RSA${cot_rsa}_SHA${cot_sha} \
		--cot_verify_key tests/keys/rsa${cot_rsa}.pub.pem \
		--deterministic \
		$args

	verify_image $soc $rev mode2aes2 $rot_rsa $rot_sha cot $cot_rsa $cot_sha $@
}

make_modegcm_bl1_image() {
	local soc=$1
	local rev=$2
	shift 2

	local slug=$(make_slug $soc $rev modegcm $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev modegcm $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_GCM \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--gcm_aes_key tests/keys/aes-gcm.bin \
		--deterministic \
		$args

	verify_image $soc $rev modegcm $@
}

make_cot_modegcm_bl1_image() {
	local soc=$1
	local rev=$2
	local cot_rsa=$3
	local cot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev modegcm cot $cot_rsa $cot_sha $@)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev modegcm cot $cot_rsa $cot_sha $@

	args=$(parse_config $@)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_GCM \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--gcm_aes_key tests/keys/aes-gcm.bin \
		--cot_algorithm RSA${cot_rsa}_SHA${cot_sha} \
		--cot_verify_key tests/keys/rsa${cot_rsa}.pub.pem \
		--deterministic \
		$args

	verify_image $soc $rev modegcm cot $cot_rsa $cot_sha $@
}

make_sv_chain_image() {
	local bl2_rsa=$1
	local bl2_sha=$2
	local bl3_rsa=$3
	local bl3_sha=$4
	shift 4

	local bl2_slug=rsa${bl2_rsa}-sha${bl2_sha}
	local bl3_slug=rsa${bl3_rsa}-sha${bl3_sha}

	mkdir -p tests/data/generated

	args=$(parse_config $@)

	$RUN $SOCSEC make_sv_chain_image \
		--algorithm RSA${bl2_rsa}_SHA${bl2_sha} \
		--image_relative_path tests/data/ \
		--cot_part bl2.bin:generated/bl2.${bl2_slug}.signed.bin:tests/keys/rsa${bl2_rsa}.pem:tests/keys/rsa${bl2_rsa}.pub.pem \
		bl3.bin:generated/bl3.${bl3_slug}.signed.bin:tests/keys/rsa${bl3_rsa}.pem:tests/keys/rsa${bl3_rsa}.pub.pem \
		$args
}

make_mode2aes2_bl1_image_from_rsa_priv() {
	local soc=$1
	local rev=$2
	local rot_rsa=$3
	local rot_sha=$4
	shift 4

	local slug=$(make_slug $soc $rev mode2aes2 $rot_rsa $rot_sha rsa-priv)

	mkdir -p tests/data/generated/${slug}

	make_otp $soc $rev mode2aes2 $rot_rsa $rot_sha rsa-priv

	args=$(parse_config rsa-priv)

	$RUN $SOCSEC make_secure_bl1_image \
		--soc $soc \
		--algorithm AES_RSA${rot_rsa}_SHA${rot_sha} \
		--bl1_image $BL1_IMAGE \
		--output tests/data/generated/${slug}/bl1.signed.bin \
		--rsa_sign_key tests/keys/rsa${rot_rsa}.pem \
		--aes_key tests/keys/aes-oem.bin \
		--rsa_aes tests/keys/rsa${rot_rsa}.pem \
		--deterministic \
		$args

	verify_image $soc $rev mode2aes2 $rot_rsa $rot_sha rsa-priv
}

clean() {
	coverage erase
}

exercise_no_args() {
	$RUN $SOCSEC || true
}

exercise_help() {
	$RUN $SOCSEC --help
}

exercise_bl1_mode2() {
	for rot_rsa in 1024 2048 3072 4096
	do
		for rot_sha in 224 256 384 512
		do
			make_mode2_bl1_image 2600 a1 $rot_rsa $rot_sha &
			make_mode2aes1_bl1_image 2600 a1 $rot_rsa $rot_sha &
			make_mode2aes2_bl1_image 2600 a1 $rot_rsa $rot_sha &
		done

		wait
	done
}

exercise_bl1_cot_mode2() {
	for rot_rsa in 1024 2048 3072 4096
	do
		for rot_sha in 224 256 384 512
		do
			for cot_rsa in 1024 2048 3072 4096
			do
				for cot_sha in 224 256 384 512
				do
					make_cot_mode2_bl1_image \
						2600 a1 \
						$rot_rsa $rot_sha \
						$cot_rsa $cot_sha &

					make_cot_mode2aes1_bl1_image \
						2600 a1 \
						$rot_rsa $rot_sha \
						$cot_rsa $cot_sha &

					make_cot_mode2aes2_bl1_image \
						2600 a1 \
						$rot_rsa $rot_sha \
						$cot_rsa $cot_sha &

				done

				wait
			done
		done
	done
}

exercise_bl1_gcm() {
	make_modegcm_bl1_image 2600 a1

	for cot_rsa in 1024 2048 3072 4096
	do
		for cot_sha in 224 256 384 512
		do
			make_cot_modegcm_bl1_image 2600 a1 $cot_rsa $cot_sha &
		done

		wait
	done
}

exercise_sv_chain_image() {
	for rsa in 1024 2048 3072 4096
	do
		for sha in 224 256 384 512
		do
			make_sv_chain_image $rsa $sha $rsa $sha &
		done

		wait
	done
}

exercise_signing_helpers() {
	for helper in sign-stream sign-file
	do
		for algo in "1024 224" "2048 256" "3072 384" "4096 512"
		do
			make_mode2_bl1_image 2600 a1 $algo $helper &
			make_cot_mode2_bl1_image 2600 a1 $algo $algo $helper &
			make_mode2aes1_bl1_image 2600 a1 $algo $helper &
			make_cot_mode2aes1_bl1_image 2600 a1 $algo $algo $helper &
			make_mode2aes2_bl1_image 2600 a1 $algo $helper &
			make_cot_mode2aes2_bl1_image 2600 a1 $algo $algo $helper &
			make_cot_modegcm_bl1_image 2600 a1 $algo $helper &

			wait
		done

		make_modegcm_bl1_image 2600 a1 $helper
	done
}

exercise_soc_revs() {
	for soc in 2600 1030
	do
		for rev in a0 a1 a2
		do
			if [ $soc = "1030" -a $rev != 'a0' ]
			then
				continue
			fi

			if [ $soc = "2600" -a $rev = 'a1' ]
			then
				continue
			fi

			for algo in "1024 224" "2048 256" "3072 384" "4096 512"
			do
				make_mode2_bl1_image $soc $rev $algo &
				make_cot_mode2_bl1_image $soc $rev $algo $algo &
				make_mode2aes1_bl1_image $soc $rev $algo &
				make_cot_mode2aes1_bl1_image $soc $rev $algo $algo &
				make_mode2aes2_bl1_image $soc $rev $algo &
				make_cot_mode2aes2_bl1_image $soc $rev $algo $algo &

				make_mode2aes2_bl1_image_from_rsa_priv \
					$soc $rev $algo &

				if [ $soc = "2600" ]
				then
					make_cot_modegcm_bl1_image \
						$soc $rev $algo &
				fi

				wait
			done

			if [ $soc = "2600" ]
			then
				make_modegcm_bl1_image $soc $rev
			fi
		done
	done
}

exercise_mode2v2() {
	for mode in mode2v2 mode2v2aes1 mode2v2aes2priv mode2v2aes2pub
	do
		for rsa_padding in pkcs1 pss
		do
			for algo in "2048 256" "3072 384" "4096 512"
			do
				echo make_${mode}${rsa_padding}_bl1_image 1030 a1 ${algo}
				make_${mode}${rsa_padding}_bl1_image 1030 a1 ${algo}
			done
		done
	done
}

exercise_bl1_mode2_big() {
	for rot_rsa in 2048 3072 4096
	do
		for rot_sha in 256 384 512
		do
			make_mode2_bl1_image 2600 a3 $rot_rsa $rot_sha big &
			make_mode2aes1_bl1_image 2600 a3 $rot_rsa $rot_sha big &
			make_mode2aes2_bl1_image 2600 a3 $rot_rsa $rot_sha big &
		done

		wait
	done
}

exercise_bl1_mode2_little() {
	for rot_rsa in 2048 3072 4096
	do
		for rot_sha in 256 384 512
		do
			make_mode2_bl1_image 2600 a3 $rot_rsa $rot_sha little &
			make_mode2aes1_bl1_image 2600 a3 $rot_rsa $rot_sha little &
			make_mode2aes2_bl1_image 2600 a3 $rot_rsa $rot_sha little &
		done

		wait
	done
}

exercise_bl1_ecdsa() {
	make_ecdsa_bl1_image 1030 a1
	make_ecdsaaes1_bl1_image 1030 a1

	for rot_rsa in 2048 3072 4096
	do
		make_ecdsaaes2_bl1_image 1030 a1 ${rot_rsa}
	done
}

compare_results() {
	find tests/data/reference -type f | sort | while read R
	do
		G=tests/data/generated/$(echo $R | sed 's|tests/data/reference/||')
		cmp $R $G
	done
}

run() {
	rm -rf tests/data/generated

	exercise_no_args
	exercise_help
	exercise_bl1_mode2
	exercise_bl1_cot_mode2
	exercise_bl1_gcm
	exercise_sv_chain_image
	exercise_signing_helpers
	exercise_soc_revs
	exercise_mode2v2
	exercise_bl1_mode2_big
	exercise_bl1_mode2_little
	exercise_bl1_ecdsa

	compare_results
}

report() {
	coverage combine -a
	coverage html --include='*/socsec/otptool.py*,*/socsec/socsec.py,*/socsec/__init__.py' || true
}

clean
run
report
